# -*- coding: utf-8 -*-
'''
设置节点的颜色和形状
'''
import networkx as nx
from neo4j import GraphDatabase
import pandas as pd
import random

# from collections import defaultdict

# url = 'bolt://159.1.44.26:8687'
url = 'neo4j://127.0.0.1:7687'
username = 'neo4j'
password = '759503714'

driver = GraphDatabase.driver(url, auth=(username, password))


def import_networkx_graph_to_neo4j(tx, graph):
    print('-' * 20, '操作Neo4j图数据库', '-' * 20)
    tx.run("MATCH (N) DETACH DELETE N")

    children_id = 1
    for node in graph.nodes():
        # print(node)
        node_type = G.nodes[node].get('node_type', None)
        demand_no_lst = G.nodes[node].get('demand_no', None)
        demand_info_lst = G.nodes[node].get('demand_info', None)
        # print(demand_info_lst)
        change_content_lst = G.nodes[node].get('change_content', None)
        change_count = G.nodes[node].get('change_count', None)
        # print(change_count)
        main_req_count = G.nodes[node].get('main_req_count', None)
        related_req_count = G.nodes[node].get('related_req_count', None)
        neighbors = set(G.predecessors(node)).union(set(G.successors(node))) - {node}
        # print('neighbors:', neighbors)
        system_count = len(neighbors)

        change_count_new = str(change_count) + ' (主: ' + str(main_req_count) + ' 关联: ' + str(related_req_count) + ')'

        # # 作为主系统需要配合的换版关联系统数
        # pre_neighbors = set(G.predecessors(node)) - {node}
        # print('pre_neighbors:', pre_neighbors)
        # pre_system_count = len(pre_neighbors)
        # # 作为关联系统需要配合的换版主系统数
        # succ_neighbors = set(G.successors(node)) - {node}
        # print('succ_neighbors:', succ_neighbors)
        # succ_system_count = len(succ_neighbors)
        info_lst = []
        for i in range(len(demand_info_lst)):
            info_lst.append({"id": demand_no_lst[i], "label": demand_info_lst[i],
                             "children": [{"id": children_id, "label": change_content_lst[i]}]})
            children_id += 1

        # create_node_query = f"CREATE (:{node_type} {{name: $name, status: $status, ReqCount: $change_count, " \
        #                     f"MainReqCount: $main_req_count, RelatedReqCount: $related_req_count,"\
        #                     f"SysCount: $system_count, info: $info, "\
        #                     f"PreSysCount: $pre_system_count, SuccSysCount: $succ_system_count}})"
        # tx.run(create_node_query, name=node, status=0, change_count=change_count, main_req_count=main_req_count,
        #        related_req_count=related_req_count, system_count=system_count, pre_system_count=pre_system_count,
        #        succ_system_count=succ_system_count, info=str(info_lst))

        # create_node_query = f"CREATE (:{node_type} {{name: $name, status: $status, ReqCount: $change_count, " \
        #                     f"MainReqCount: $main_req_count, RelatedReqCount: $related_req_count, " \
        #                     f"SysCount: $system_count, info: $info}})"

        create_node_query = f"CREATE (:{node_type} {{name: $name, status: $status, ReqCount: $requests_count, " \
                            f"ReqCountStr: $change_count, MainReqCount: $main_req_count, " \
                            f"RelatedReqCount: $related_req_count, " \
                            f"SysCount: $system_count, info: $info, isImportant: $is_important}})"
        # tx.run(create_node_query, name=node, status=0, change_count=change_count, main_req_count=main_req_count,
        #        related_req_count=related_req_count, system_count=system_count, info=str(info_lst))

        rand_num = random.random()
        if rand_num < 0.5:
            status = 1
        elif rand_num < 0.7:
            status = 2
        elif rand_num < 0.9:
            status = 3
        else:
            status = 4
        tx.run(create_node_query, name=node, status=status, requests_count=change_count,
               change_count=change_count_new, main_req_count=main_req_count, related_req_count=related_req_count,
               system_count=system_count, info=str(info_lst), is_important=0)

    for edge in graph.edges(data=True):
        source, target, data = edge
        print(source, target, data)
        source_type, target_type = G.nodes[source].get('node_type', None), G.nodes[target].get('node_type', None)

        create_edge_query = f"MATCH (source:{source_type} {{name: $source_name}}), (target:{target_type} {{name: $target_name}}) " \
                            f"CREATE (source)-[:关联 {{weight: $weight}}]->(target)"
        tx.run(create_edge_query, source_name=source, target_name=target,
               weight=str(data.get('weight')))


# 数据读取与处理
df_origin = pd.read_excel(".\\data\\换版审批列表.xls", skiprows=3)

nodes_lst = list(df_origin['系统'].unique())

# ------------------------需求维度信息-------------------------
demand_info_dict = {}
for i in range(df_origin.shape[0]):
    system_name = str(df_origin['系统'][i])
    demand_no = str(df_origin['需求编号'][i])
    demand_name = str(df_origin['需求标题'][i])
    change_content = str(df_origin['变更内容'][i])

    if demand_no not in demand_info_dict:
        demand_info_dict[demand_no] = {'demand_name': demand_name, 'change_content': [],
                                       'main_system': '', 'related_systems': []}
    if df_origin['是否主系统'][i] == '是':
        demand_info_dict[demand_no]['main_system'] = system_name

    demand_info_dict[demand_no]['related_systems'].append(system_name)
    demand_info_dict[demand_no]['change_content'].append(change_content)

# print(demand_info_dict)

# ------------------------系统维度信息------------------------
system_info_dict = {}
for i in range(df_origin.shape[0]):
    system_name = str(df_origin['系统'][i])
    is_main_system_flag = str(df_origin['是否主系统'][i])
    demand_no = str(df_origin['需求编号'][i])
    demand_name = str(df_origin['需求标题'][i])
    change_content = str(df_origin['变更内容'][i])

    if system_name not in system_info_dict:
        system_info_dict[system_name] = {'demand_no': [], 'demand_info': [], 'change_content': [], 'change_count': 0,
                                         'main_req_count': 0, 'related_req_count': 0}

    system_info_dict[system_name]['demand_no'].append(demand_no)
    # system_info_dict[system_name]['demand_info'].append(demand_no + demand_name)
    system_info_dict[system_name]['change_content'].append(change_content)
    system_info_dict[system_name]['change_count'] += 1
    if is_main_system_flag == '是':
        system_info_dict[system_name]['main_req_count'] += 1
        system_info_dict[system_name]['demand_info'].insert(0, '[主]' + demand_no + demand_name)
    else:
        system_info_dict[system_name]['related_req_count'] += 1
        system_info_dict[system_name]['demand_info'].append(demand_no + demand_name)

print(system_info_dict)

# -------------------------创建边和节点-------------------------
G = nx.MultiDiGraph()

# 创建节点
nodes_count = 0
for system_name in system_info_dict:
    print('node:', system_name)
    nodes_count += 1
    G.add_node(system_name, node_type='系统', demand_no=system_info_dict[system_name]['demand_no'],
               demand_info=system_info_dict[system_name]['demand_info'],
               change_content=system_info_dict[system_name]['change_content'],
               change_count=system_info_dict[system_name]['change_count'],
               main_req_count=system_info_dict[system_name]['main_req_count'],
               related_req_count=system_info_dict[system_name]['related_req_count'])
print('nodes_count:', nodes_count)

# 创建边
for demand_no in demand_info_dict:
    main_system = demand_info_dict[demand_no]['main_system']
    related_systems_lst = demand_info_dict[demand_no]['related_systems']
    demand_name = demand_info_dict[demand_no]['demand_name']
    if main_system and len(related_systems_lst) > 1:
        print(demand_no, related_systems_lst)
        for related_system in related_systems_lst:
            if related_system != main_system:
                print('start: %s, end: %s' % (related_system, main_system))
                G.add_edge(related_system, main_system, weight=str(demand_no))

# 对孤立点增加自连接的边
for node in G.nodes():
    neighbors = set(G.predecessors(node)).union(set(G.successors(node)))
    if len(neighbors) == 0:
        # print(node)
        G.add_edge(node, node, weight='')

# 节点间的多条边聚合
edge_weights = {}

for u, v, data in G.edges(data=True):
    print(u, v, data)
    weight = data['weight']
    if (u, v) in edge_weights:
        edge_weights[(u, v)].append(weight)
    else:
        edge_weights[(u, v)] = [weight]

G.remove_edges_from(list(G.edges))
for (u, v), weights in edge_weights.items():
    G.add_edge(u, v, weight=','.join(weights))

for u, v, data in G.edges(data=True):
    print(f"Edge from {u} to {v}, weights: {data['weight']}")

# print(G.nodes())
# print(set(G.predecessors('积存金系统')))
# print(set(G.successors('积存金系统')))
# neighbors = set(G.predecessors('积存金系统')).union(set(G.successors('积存金系统')))
# print(len(neighbors))
# print(list(G.neighbors('积存金系统')))
# print(len(list(G.neighbors('积存金系统'))))
# print(G.in_degree('图像识别服务系统'))
# print(G.out_degree('图像识别服务系统'))

# 数据写入neo4j图数据库
with driver.session() as session:
    session.execute_write(import_networkx_graph_to_neo4j, G)
